#include "scheduler.h"
#include "printf.h"
#include "pmm.h"
#include <stddef.h>

// 任务表
static task_t task_table[MAX_TASKS];

// 当前运行任务
static task_t* current_task = NULL;

// 下一个可用PID
static uint32_t next_pid = 1;

// 全局时钟tick计数器(由时钟中断更新)
static volatile uint32_t system_ticks = 0;

// 字符串复制
static void my_strncpy(char* dest, const char* src, size_t n) {
    size_t i;
    for (i = 0; i < n - 1 && src[i] != '\0'; i++) {
        dest[i] = src[i];
    }
    dest[i] = '\0';
}

// 内存清零
static void my_memset(void* s, int c, size_t n) {
    unsigned char* p = (unsigned char*)s;
    for (size_t i = 0; i < n; i++) {
        p[i] = (unsigned char)c;
    }
}

/**
 * 初始化调度器
 */
void scheduler_init(void) {
    printf("\n=== 调度器初始化 ===\n");
    
    // 清空任务表
    for (int i = 0; i < MAX_TASKS; i++) {
        task_table[i].state = TASK_UNUSED;
        task_table[i].pid = 0;
        task_table[i].next = NULL;
        task_table[i].wait_channel = NULL;
    }
    
    current_task = NULL;
    next_pid = 1;
    system_ticks = 0;
    
    printf("任务表大小: %d\n", MAX_TASKS);
    printf("=== 调度器初始化完成 ===\n");
}

/**
 * 创建新任务
 */
int create_task(const char* name, void (*entry)(void*), void* arg, uint32_t time_slice) {
    if (!entry) {
        printf("[错误] 任务入口函数为空\n");
        return -1;
    }
    
    // 查找空闲任务槽
    for (int i = 0; i < MAX_TASKS; i++) {
        if (task_table[i].state == TASK_UNUSED) {
            task_t* task = &task_table[i];
            
            // 初始化任务
            my_memset(task, 0, sizeof(task_t));
            task->pid = next_pid++;
            task->state = TASK_READY;
            task->entry = entry;
            task->arg = arg;
            task->time_slice = time_slice;
            task->elapsed_time = 0;
            task->wait_channel = NULL;
            task->sleep_until = 0;
            
            if (name) {
                my_strncpy(task->name, name, sizeof(task->name));
            }
            
            printf("[调度器] 创建任务: PID=%d, 名称=%s, 时间片=%dms\n",
                   task->pid, task->name, task->time_slice);
            
            return task->pid;
        }
    }
    
    printf("[错误] 任务表已满\n");
    return -1;
}

/**
 * 轮转调度算法
 * 简单遍历任务表,按顺序挑选第一个READY状态的任务
 */
void schedule(void) {
    task_t* next_task = NULL;
    
    // 1. 如果当前任务还在运行且时间片未用完,继续运行
    if (current_task && 
        current_task->state == TASK_RUNNING && 
        current_task->elapsed_time < current_task->time_slice) {
        return;
    }
    
    // 2. 将当前任务状态改为READY(如果它还在运行)
    if (current_task && current_task->state == TASK_RUNNING) {
        current_task->state = TASK_READY;
        current_task->elapsed_time = 0;
    }
    
    // 3. 轮转查找下一个READY任务
    // 从当前任务的下一个开始查找,实现公平轮转
    int start_idx = current_task ? (current_task - task_table + 1) % MAX_TASKS : 0;
    
    for (int i = 0; i < MAX_TASKS; i++) {
        int idx = (start_idx + i) % MAX_TASKS;
        task_t* task = &task_table[idx];
        
        if (task->state == TASK_READY) {
            next_task = task;
            break;
        }
    }
    
    // 4. 切换到新任务
    if (next_task) {
        current_task = next_task;
        current_task->state = TASK_RUNNING;
        current_task->elapsed_time = 0;
        
        printf("[调度] 切换到任务: %s (PID=%d)\n", 
               current_task->name, current_task->pid);
        
        // 简化版本:直接调用任务函数
        // 真实OS会进行上下文切换
        if (current_task->entry) {
            current_task->entry(current_task->arg);
        }
    } else {
        current_task = NULL;
        printf("[调度] 无就绪任务,CPU空闲\n");
    }
}

/**
 * 获取当前任务
 */
task_t* get_current_task(void) {
    return current_task;
}

/**
 * 打印所有任务状态
 * 修复: 使用简单的分段打印,避免复杂的格式化
 */
void print_tasks(void) {
    printf("\n=== 任务列表 ===\n");
    printf("PID | 状态   | 名称         | 时间片 | 已用时间\n");
    printf("--------------------------------------------------\n");
    
    for (int i = 0; i < MAX_TASKS; i++) {
        task_t* task = &task_table[i];
        if (task->state != TASK_UNUSED) {
            const char* state_str;
            switch (task->state) {
                case TASK_READY:    state_str = "就绪"; break;
                case TASK_RUNNING:  state_str = "运行"; break;
                case TASK_SLEEPING: state_str = "睡眠"; break;
                case TASK_ZOMBIE:   state_str = "僵尸"; break;
                default:            state_str = "未知"; break;
            }
            
            // 分段打印,避免复杂格式化
            printf("%d   | %s | %s", task->pid, state_str, task->name);
            
            // 填充空格使对齐(简单实现)
            int name_len = 0;
            for (int j = 0; task->name[j] != '\0' && j < 32; j++) {
                name_len++;
            }
            for (int j = name_len; j < 12; j++) {
                printf(" ");
            }
            
            printf(" | %dms   | %dms\n", task->time_slice, task->elapsed_time);
        }
    }
    printf("==================================================\n\n");
}

/**
 * 任务主动让出CPU
 */
void task_yield(void) {
    if (current_task) {
        printf("[调度] 任务%s主动让出CPU\n", current_task->name);
        current_task->state = TASK_READY;
        schedule();
    }
}

// ===== sleep/wakeup 实现 =====

/**
 * 当前任务进入睡眠(阻塞)
 * 这是避免忙等待的关键!
 */
void task_sleep(void* channel) {
    if (!current_task) {
        printf("[错误] 没有当前任务\n");
        return;
    }
    
    printf("[调度] 任务%s进入睡眠(channel=%p)\n", 
           current_task->name, channel);
    
    current_task->state = TASK_SLEEPING;
    current_task->wait_channel = channel;
    
    // 切换到其他任务
    schedule();
}

/**
 * 唤醒等待在指定通道的所有任务
 */
void task_wakeup(void* channel) {
    int wakeup_count = 0;
    
    for (int i = 0; i < MAX_TASKS; i++) {
        task_t* task = &task_table[i];
        if (task->state == TASK_SLEEPING && task->wait_channel == channel) {
            task->state = TASK_READY;
            task->wait_channel = NULL;
            wakeup_count++;
            printf("[调度] 唤醒任务: %s (PID=%d)\n", task->name, task->pid);
        }
    }
    
    if (wakeup_count > 0) {
        printf("[调度] 共唤醒 %d 个任务\n", wakeup_count);
    }
}

/**
 * 当前任务睡眠指定时间(ms)
 */
void task_sleep_ms(uint32_t ms) {
    if (!current_task) {
        return;
    }
    
    printf("[调度] 任务%s睡眠%dms\n", current_task->name, ms);
    
    current_task->state = TASK_SLEEPING;
    current_task->sleep_until = system_ticks + ms;
    
    // 切换到其他任务
    schedule();
}

/**
 * 时钟tick处理
 * 在时钟中断处理函数中每1ms调用一次
 */
void scheduler_tick(void) {
    system_ticks++;
    
    // 检查是否有睡眠超时的任务需要唤醒
    for (int i = 0; i < MAX_TASKS; i++) {
        task_t* task = &task_table[i];
        if (task->state == TASK_SLEEPING && 
            task->sleep_until > 0 && 
            system_ticks >= task->sleep_until) {
            
            task->state = TASK_READY;
            task->sleep_until = 0;
            printf("[调度] 任务%s睡眠超时,唤醒\n", task->name);
        }
    }
}

